package com.ys.load.controller;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.security.PrivateKey;
import java.util.Date;

import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.util.ObjectUtils;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.alibaba.fastjson.JSONObject;
import com.wechat.pay.contrib.apache.httpclient.WechatPayHttpClientBuilder;
import com.wechat.pay.contrib.apache.httpclient.util.PemUtil;
import com.wechat.pay.java.core.Config;
import com.wechat.pay.java.core.RSAAutoCertificateConfig;
import com.wechat.pay.java.service.payments.nativepay.NativePayService;
import com.wechat.pay.java.service.payments.nativepay.model.Amount;
import com.wechat.pay.java.service.payments.nativepay.model.PrepayRequest;
import com.wechat.pay.java.service.payments.nativepay.model.PrepayResponse;
import com.ys.load.common.CurrencyMessage;
import com.ys.load.common.ReturnResult;
import com.ys.load.entity.BooksLoadLogs;
import com.ys.load.entity.BooksOrder;
import com.ys.load.entity.BooksUrl;
import com.ys.load.mapper.BooksLoadLogsMapper;
import com.ys.load.mapper.BooksOrderMapper;
import com.ys.load.mapper.BooksUrlMapper;
import com.ys.load.util.BooksUtil;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;

/**
 * 电子书下载控制器
 * @author yusong
 * @date 20241104
 */
@Slf4j
@RestController
@RequestMapping(value = "/download")
@Api(value = "电子书下载控制器",tags = {"电子书下载控制器"})
public class DownloadController {
	
	@Value("${wechat.pay.merchantId}")
	private String merchantId;
	@Value("${wechat.pay.privateKeyPath}")
	private String privateKeyPath;
	@Value("${wechat.pay.merchantSerialNumber}")
	private String merchantSerialNumber;
	@Value("${wechat.pay.apiV3key}")
	private String apiV3key;
	@Value("${wechat.pay.appid}")
	private String appid;
	@Value("${wechat.pay.notifyUrl}")
	private String notifyUrl;
	@Value("${wechat.pay.imageUrl}")
	private String imageUrl;
	@Value("${wechat.pay.privateKey}")
	private String privateKey;
	@Autowired
	private BooksUrlMapper booksUrlMapper;
	
	@Autowired
	private BooksOrderMapper booksOrderMapper;
	
	@Autowired
	private BooksLoadLogsMapper booksLoadLogsMapper;
	
	
	@ApiOperation(value="电子书下载请求地址")
	@GetMapping("/books")
	@CrossOrigin
	@ApiImplicitParam(name = "signCode", value = "电子书的唯一标识", dataType = "String", paramType = "query", required = false)
	public String books(String signCode) {
		
		//记录点击事件
		BooksLoadLogs booksLoadLogs = new BooksLoadLogs();
		booksLoadLogs.setOperateType(1);
		booksLoadLogs.setLogDesc("用户点击,资源标识signCode:" + signCode);
		booksLoadLogs.setCreateTime(new Date());
		booksLoadLogsMapper.insertBooksLoadLogs(booksLoadLogs);
		
		//根据电子书的唯一标识码 找到对应的电子书信息
		BooksUrl bu = booksUrlMapper.selectBooksUrlBySignCode(signCode);
		if(ObjectUtils.isEmpty(bu)) {
			return "未找到对应的电子书";
		}
		//电子书存在的情况下,生成该次点击的订单号 并存储在数据库
		String uuid = BooksUtil.UUIDGenerator().toString().replaceAll("-", "");//uuid作为订单号
		BooksOrder bo = new BooksOrder();
		bo.setSignCode(signCode);
		bo.setOrderNo(uuid);//订单号
		bo.setGenDate(new Date());
		int num = booksOrderMapper.insertBooksOrder(bo);
		if(num>0) {
			//生成临时订单成功 返回带订单号的收款码
			Config config = new RSAAutoCertificateConfig.Builder().merchantId(merchantId).privateKeyFromPath(privateKeyPath)//privateKeyFromPath("D:\\wechatpay\\apiclient_key.pem")//
                    .merchantSerialNumber(merchantSerialNumber).apiV3Key(apiV3key).build();
			//支付服务
			NativePayService service = new NativePayService.Builder().config(config).build();
			//支付参数设置
			PrepayRequest request = new PrepayRequest();
			Amount amount = new Amount();
			amount.setTotal(200);//单位(分)=2元
			request.setAmount(amount);
			request.setAppid(appid);//公众号--小程序
			request.setMchid(merchantId);//直连商户号
	        request.setDescription("测试商品标题");//商品描述
	        request.setNotifyUrl(notifyUrl);//通知地址 说明：有效性：1. HTTPS；2. 不允许携带查询串
	        request.setOutTradeNo(uuid);//商户订单号 说明：商户订单号
	        // 调用下单方法，得到应答
	        PrepayResponse response = service.prepay(request);
	        String codeUrl = response.getCodeUrl();//返回的支付链接
	        
	        //java生成二维码  https://blog.csdn.net/weixin_52258054/article/details/140633220
	        String imageName = uuid + "-" + System.currentTimeMillis() + ".png";
	        BooksUtil.generateQRCodeImage(codeUrl, 350, 350, imageUrl + imageName);//生成二维码
	        //把图片返回给前端
	        return imageName;
		}
		
		return "";
	}
	
	@ApiOperation(value="电子书下载请求地址")
	@GetMapping("/book")
	@CrossOrigin
	@ApiImplicitParam(name = "signCode", value = "电子书的唯一标识", dataType = "String", paramType = "query", required = false)
	public ReturnResult<BooksUrl> book(String signCode){
		//记录点击事件
		BooksLoadLogs booksLoadLogs = new BooksLoadLogs();
		booksLoadLogs.setOperateType(1);
		booksLoadLogs.setLogDesc("用户点击,资源标识signCode:" + signCode);
		booksLoadLogs.setCreateTime(new Date());
		booksLoadLogsMapper.insertBooksLoadLogs(booksLoadLogs);
		
		BooksUrl bu = booksUrlMapper.selectBooksUrlBySignCode(signCode);
		if(ObjectUtils.isEmpty(bu)) {
			return new ReturnResult<BooksUrl>(CurrencyMessage.FAIL);
		}
		//电子书存在的情况下,生成该次点击的订单号 并存储在数据库
		String uuid = BooksUtil.UUIDGenerator().toString().replaceAll("-", "");//uuid作为订单号
		BooksOrder bo = new BooksOrder();
		bo.setSignCode(signCode);
		bo.setOrderNo(uuid);//订单号
		bo.setGenDate(new Date());
		int num = booksOrderMapper.insertBooksOrder(bo);
		if(num>0) {
			//生成临时订单成功 返回带订单号的收款码
			Config config = new RSAAutoCertificateConfig.Builder().merchantId(merchantId).privateKeyFromPath(privateKeyPath)//privateKeyFromPath("D:\\wechatpay\\apiclient_key.pem")//
                    .merchantSerialNumber(merchantSerialNumber).apiV3Key(apiV3key).build();
			//支付服务
			NativePayService service = new NativePayService.Builder().config(config).build();
			//支付参数设置
			PrepayRequest request = new PrepayRequest();
			Amount amount = new Amount();
			amount.setTotal(bu.getSellPrice());//单位(分)=2元
			request.setAmount(amount);
			request.setAppid(appid);//公众号--小程序
			request.setMchid(merchantId);//直连商户号
	        request.setDescription(bu.getBookName());//商品描述==书名
	        request.setNotifyUrl(notifyUrl);//通知地址 说明：有效性：1. HTTPS；2. 不允许携带查询串
	        request.setOutTradeNo(uuid);//商户订单号 说明：商户订单号
	        // 调用下单方法，得到应答
	        PrepayResponse response = service.prepay(request);
	        String codeUrl = response.getCodeUrl();//返回的支付链接
	        
	        //java生成二维码  https://blog.csdn.net/weixin_52258054/article/details/140633220
	        String imageName = uuid + "-" + System.currentTimeMillis() + ".png";
	        BooksUtil.generateQRCodeImage(codeUrl, 350, 350, imageUrl + imageName);//生成二维码
	        bu.setImgName(imageName);
	        //把图片返回给前端
	        return new ReturnResult<BooksUrl>(bu);
		}
		return null;
	}

	
	@ApiOperation(value="外部订单验证是否支付 SUCCESS=成功")
	@GetMapping("/verifyPay")
	@CrossOrigin
	@ApiImplicitParam(name = "outTradeNo", value = "外部订单号", dataType = "String", paramType = "query", required = false)
	public String verifyPay(String outTradeNo) throws Exception{
		//TODO 通过外部订单号 判断是否支付
		PrivateKey merchantPrivateKey = PemUtil.loadPrivateKey(new ByteArrayInputStream(privateKey.getBytes("utf-8")));
		HttpClient httpClient =  WechatPayHttpClientBuilder.create().withMerchant(merchantId, merchantSerialNumber, merchantPrivateKey).withValidator((response) -> true).build();
		URIBuilder uriBuilder = new URIBuilder("https://api.mch.weixin.qq.com/v3/pay/transactions/out-trade-no/"+outTradeNo);
		uriBuilder.setParameter("mchid", merchantId);
		//完成签名并执行请求
		HttpGet httpGet = new HttpGet(uriBuilder.build());
		httpGet.addHeader("Accept", "application/json");
		CloseableHttpResponse response = (CloseableHttpResponse) httpClient.execute(httpGet);
		try {
			int statusCode = response.getStatusLine().getStatusCode();
			if (statusCode == 200) {
				String jsonStr = EntityUtils.toString(response.getEntity());
				JSONObject jo = JSONObject.parseObject(jsonStr);
				String state = jo.getString("trade_state").trim();
		          if("SUCCESS".equals(state.trim())) {
		        	  //记录支付成功信息
		        	  	BooksLoadLogs booksLoadLogs = new BooksLoadLogs();
			      		booksLoadLogs.setOperateType(2);
			      		booksLoadLogs.setLogDesc("用户点击,订单号outTradeNo:" + outTradeNo);
			      		booksLoadLogs.setCreateTime(new Date());
			      		booksLoadLogsMapper.insertBooksLoadLogs(booksLoadLogs);
			      		
		        	  return "SUCCESS";
		          }else {
		        	  return "FAILD";
		          }
		      } else if (statusCode == 204) {
		    	  return "FAILD";
		      } else {
		    	  return "FAILD";
		      }
		} finally {
			response.close();
		}
		
		
	}
	
	@ApiOperation(value="通过资源标识(signCode)获取资源下载地址")
	@GetMapping("/resourceUrl")
	@CrossOrigin
	@ApiImplicitParam(name = "signCode", value = "电子书的唯一标识", dataType = "String", paramType = "query", required = false)
	public String resourceUrl(String signCode) {
		BooksUrl bu = booksUrlMapper.selectBooksUrlBySignCode(signCode);
		return "请求地址:" + bu.getDownloadUrl() + "    分享码:" + bu.getShareCode();
	}
	
	@ApiOperation(value="电子书下载测试")
	@GetMapping("/test")
	@CrossOrigin
	public String test() throws Exception{
		

		PrivateKey merchantPrivateKey = PemUtil.loadPrivateKey(new ByteArrayInputStream(privateKey.getBytes("utf-8")));
		HttpClient httpClient =  WechatPayHttpClientBuilder.create().withMerchant("1698102898", "33A39F76EDECF75CBD3D416B5BEADC52BE108F41", merchantPrivateKey).withValidator((response) -> true).build();
		//请求URL
		  URIBuilder uriBuilder = new URIBuilder("https://api.mch.weixin.qq.com/v3/pay/transactions/out-trade-no/b06ab5a8076647ac93d9972e81507b4d") ;
		  uriBuilder.setParameter("mchid", "1698102898");
		 
		  //完成签名并执行请求
		  HttpGet httpGet = new HttpGet(uriBuilder.build());
		  httpGet.addHeader("Accept", "application/json");
		  
		  CloseableHttpResponse response = (CloseableHttpResponse) httpClient.execute(httpGet);
		   
		  try {
		      int statusCode = response.getStatusLine().getStatusCode();
		      if (statusCode == 200) {
		          System.out.println("success,return body = " + EntityUtils.toString(response.getEntity()));
		      } else if (statusCode == 204) {
		          System.out.println("success");
		      } else {
		    	  System.out.println("--------------------------------111-----------------------------------------------");
		          System.out.println("failed,resp code = " + statusCode+ ",return body = " + EntityUtils.toString(response.getEntity()));
		          throw new IOException("request failed");
		      }
		  } finally {
		      response.close();
		  }
		
		return "";
	}
	
}
